home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / x / volume14 / olvwm / patch2.03 < prev    next >
Encoding:
Text File  |  1991-08-26  |  47.7 KB  |  1,647 lines

  1. Path: uunet!cs.utexas.edu!sun-barr!cronkite.Central.Sun.COM!exodus!soliado.East.Sun.COM
  2. From: sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC)
  3. Newsgroups: comp.sources.x
  4. Subject: v14i009: olvwm - Open Look Virtual Window Manager, Patch2, Part03/03
  5. Message-ID: <19075@exodus.Eng.Sun.COM>
  6. Date: 27 Aug 91 06:00:48 GMT
  7. References: <csx-14i007-olvwm@uunet.UU.NET>
  8. Sender: news@exodus.Eng.Sun.COM
  9. Lines: 1635
  10. Approved: argv@sun.com
  11.  
  12. Submitted-by: sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC)
  13. Posting-number: Volume 14, Issue 9
  14. Archive-name: olvwm/patch2.03
  15. Patch-To: olvwm:  Volume 12, Issues 57-72 
  16. Patch-To: olvwm:  Volume 14, Issues 6
  17.  
  18. *** build/virtual.c    Sat Jun 22 20:09:31 1991
  19. --- src/virtual.c    Sat Jun 22 20:56:20 1991
  20. ***************
  21. *** 12,19 ****
  22.   #include "defaults.h"
  23.   #include "resources.h"
  24.   #include "st.h"
  25.   
  26. ! static char     sccsid[] = "@(#)virtual.c    1.3 olvwm version 4/17/91";
  27.   
  28.   #define TRUE    (1)
  29.   #define FALSE    (0)
  30. --- 12,22 ----
  31.   #include "defaults.h"
  32.   #include "resources.h"
  33.   #include "st.h"
  34. + #include "menu.h"
  35. + #include "list.h"
  36. + #include "patchlevel.h"
  37.   
  38. ! static char     sccsid[] = "@(#)virtual.c    1.4 olvwm version 6/22/91";
  39.   
  40.   #define TRUE    (1)
  41.   #define FALSE    (0)
  42. ***************
  43. *** 36,69 ****
  44.   int    VDMWidth, VDMHeight;
  45.   int    VDMOutlineX, VDMOutlineY;
  46.   int    VDMOutlineWidth, VDMOutlineHeight;
  47.   extern long WorkspaceColorPixel;
  48.   
  49.   int    VirtualBackgroundColorSet = FALSE;
  50.   int    VirtualForegroundColorSet = FALSE;
  51.   int    VirtualFontColorSet = FALSE;
  52.   
  53.   extern GC RootGC;
  54.   static GC    VDMGC = NULL;
  55.   
  56.   MakeVirtualDesktop(dpy)
  57.       Display    *dpy;
  58.   
  59.   {
  60.       int    width, height;
  61.   
  62.       sscanf(GRV.VirtualDesktop, "%dx%d", &width, &height);
  63. !     if (width < DisplayWidth(dpy,DefaultScreen(dpy)))
  64. !        width = width * DisplayWidth(dpy,DefaultScreen(dpy));
  65. !     if (height < DisplayHeight(dpy,DefaultScreen(dpy)))
  66. !        height = height * DisplayHeight(dpy,DefaultScreen(dpy));
  67.   
  68. !     VirtualDesktopWidth = width;
  69. !     VirtualDesktopHeight = height;
  70.       VirtualDesktopX = 0;
  71.       VirtualDesktopY = 0;
  72.       VirtualContext = XUniqueContext();
  73.   }
  74.   
  75.   MakeVDM(dpy)
  76.       Display    *dpy;
  77.   
  78. --- 39,163 ----
  79.   int    VDMWidth, VDMHeight;
  80.   int    VDMOutlineX, VDMOutlineY;
  81.   int    VDMOutlineWidth, VDMOutlineHeight;
  82. + int    VDMRows, VDMCols;
  83.   extern long WorkspaceColorPixel;
  84.   
  85.   int    VirtualBackgroundColorSet = FALSE;
  86.   int    VirtualForegroundColorSet = FALSE;
  87.   int    VirtualFontColorSet = FALSE;
  88. + int    VirtualGridColorSet = False;
  89.   
  90.   extern GC RootGC;
  91.   static GC    VDMGC = NULL;
  92.   
  93. + static int VDMMenuAction();
  94. + List    *VWList = NULL_LIST;
  95. + static Button VDMButtons[] = {
  96. + #define VDM_MENU_RIGHT    0
  97. +     { "Move Right", False, Enabled, {VDMMenuAction, (void *) NULL} },
  98. + #define VDM_MENU_LEFT    1
  99. +     { "Move Left", False, Enabled, {VDMMenuAction, (void *) NULL} },
  100. + #define VDM_MENU_UP    2
  101. +     { "Move Up", False, Enabled, {VDMMenuAction, (void *) NULL} },
  102. + #define VDM_MENU_DOWN    3
  103. +     { "Move Down", False, Enabled, {VDMMenuAction, (void *) NULL} },
  104. + #define VDM_MENU_RIGHT_UP    4
  105. +     { "Move Right/Up", False, Enabled, {VDMMenuAction, (void *) NULL} },
  106. + #define VDM_MENU_RIGHT_DOWN    5
  107. +     { "Move Right/Down", False, Enabled, {VDMMenuAction, (void *) NULL} },
  108. + #define VDM_MENU_LEFT_UP    6
  109. +     { "Move Left/Up", False, Enabled, {VDMMenuAction, (void *) NULL} },
  110. + #define VDM_MENU_LEFT_DOWN    7
  111. +     { "Move Left/Down", False, Enabled, {VDMMenuAction, (void *) NULL} },
  112. + #define VDM_MENU_HOME    8
  113. +     { "Move Home", False, Enabled, {VDMMenuAction, (void *) NULL} },
  114. + };
  115. + Menu VDMMenu = { "OLVWM 2.1", VDMButtons, 9, -0, True, (FuncPtr) MakeMenu};
  116. + #define VDMSelectMask (ButtonPressMask | ButtonReleaseMask | \
  117. +             KeyPressMask | KeyReleaseMask | \
  118. +             PointerMotionMask | ExposureMask | StructureNotifyMask)
  119.   MakeVirtualDesktop(dpy)
  120.       Display    *dpy;
  121.   
  122.   {
  123.       int    width, height;
  124. +     char temp[4];
  125. +     int    dw = DisplayWidth(dpy, DefaultScreen(dpy));
  126. +     int    dh = DisplayHeight(dpy, DefaultScreen(dpy));
  127. +     static int done_menu = False;
  128.   
  129.       sscanf(GRV.VirtualDesktop, "%dx%d", &width, &height);
  130. !     if (width < dw)
  131. !         VDMCols = width;
  132. !     else VDMCols = ceil((double) width / dw);
  133. !     if (height < dh)
  134. !     VDMRows = height;
  135. !     else VDMRows = ceil((double) height / dh);
  136.   
  137. !     VirtualDesktopWidth = VDMCols * dw;
  138. !     VirtualDesktopHeight = VDMRows * dh;
  139.       VirtualDesktopX = 0;
  140.       VirtualDesktopY = 0;
  141.       VirtualContext = XUniqueContext();
  142. +     VDMOutlineWidth = ceil((double) dw / GRV.VDMScale);
  143. +     VDMOutlineHeight = ceil((double) dh / GRV.VDMScale);
  144. +     if (GRV.VirtualGrid) {
  145. +         VDMWidth = VDMCols * VDMOutlineWidth;
  146. +         VDMHeight = VDMRows * VDMOutlineHeight;
  147. +     }
  148. +     else {
  149. +     VDMWidth = VirtualDesktopWidth / GRV.VDMScale;
  150. +     VDMHeight = VirtualDesktopHeight / GRV.VDMScale;
  151. +     }
  152. +     VDMOutlineX = 0;
  153. +     VDMOutlineY = 0;
  154. +     if (!done_menu) {
  155. +         sprintf(temp, "%0d", PATCHLEVEL);
  156. +         width = strlen(VDMMenu.title);
  157. +         VDMMenu.title[width - 1] = temp[0];
  158. +         MenuCreate(dpy, &VDMMenu);
  159. +     done_menu = True;
  160. +     }
  161.   }
  162.   
  163. + VDMGrabKey(dpy, keysym)
  164. +     Display    *dpy;
  165. +     int        keysym;
  166. + {
  167. + int    keycode;
  168. + static int meta_mask = 0, shift_mask, control_mask;
  169. +     if (meta_mask == 0) {
  170. +         keycode = XKeysymToKeycode(dpy, XK_Meta_L);
  171. +         meta_mask = FindModifierMask(keycode);
  172. +     if (meta_mask == 0)
  173. +         return;
  174. +         keycode = XKeysymToKeycode(dpy, XK_Shift_L);
  175. +         shift_mask = FindModifierMask(keycode);
  176. +         keycode = XKeysymToKeycode(dpy, XK_Control_L);
  177. +         control_mask = FindModifierMask(keycode);
  178. +     }
  179. +     keycode = XKeysymToKeycode(dpy, keysym);
  180. +     if (keycode == 0)
  181. +     return;
  182. +     XGrabKey(dpy, keycode, meta_mask,
  183. +           DefaultRootWindow(dpy), False, GrabModeAsync, GrabModeAsync);
  184. +     XGrabKey(dpy, keycode, meta_mask | shift_mask,
  185. +           DefaultRootWindow(dpy), False, GrabModeAsync, GrabModeAsync);
  186. +     XGrabKey(dpy, keycode, meta_mask | control_mask,
  187. +           DefaultRootWindow(dpy), False, GrabModeAsync, GrabModeAsync);
  188. +     XGrabKey(dpy, keycode, meta_mask | control_mask | shift_mask,
  189. +           DefaultRootWindow(dpy), False, GrabModeAsync, GrabModeAsync);
  190. + }
  191.   MakeVDM(dpy)
  192.       Display    *dpy;
  193.   
  194. ***************
  195. *** 76,120 ****
  196.       XSizeHints *sizeHints;
  197.       XWMHints *wmHints;
  198.       XClassHint *classHints;
  199. !     int x, y, width, height, dummy, flags;
  200.       Pixmap pm = None;
  201.       unsigned attrMask;
  202. !  
  203. !     width = VirtualDesktopWidth / GRV.VDMScale + 1;
  204. !     height = VirtualDesktopHeight / GRV.VDMScale + 1;
  205.   
  206.       sizeHints = XAllocSizeHints();
  207.       sizeHints->flags = PBaseSize;
  208. !     sizeHints->base_width = width;
  209. !     sizeHints->base_height = height;
  210. !     sizeHints->min_width = DisplayWidth(dpy, DefaultScreen(dpy)) /
  211. !                 GRV.VDMScale + 1;
  212. !     sizeHints->min_height = DisplayHeight(dpy, DefaultScreen(dpy)) /
  213. !                 GRV.VDMScale + 1;
  214. !     sizeHints->flags = USPosition|PMinSize;
  215.       flags = XParseGeometry(GRV.VirtualGeometry, &x, &y, &dummy, &dummy);
  216.       if (flags & XValue)
  217.       if (flags & XNegative)
  218.           sizeHints->x =
  219. !         DisplayWidth(dpy, DefaultScreen(dpy)) + x - width;
  220.       else sizeHints->x = x;
  221.       else sizeHints->x = 0;
  222.       if (flags & YValue)
  223.       if (flags & YNegative)
  224.           sizeHints->y =
  225. !         DisplayHeight(dpy, DefaultScreen(dpy)) + y - height;
  226.       else sizeHints->y = y;
  227.       else sizeHints->y = 0;
  228. !     if (sizeHints->x > DisplayWidth(dpy, DefaultScreen(dpy)) - width)
  229. !     sizeHints->x = DisplayWidth(dpy, DefaultScreen(dpy)) - width;
  230. !     if (sizeHints->y > DisplayHeight(dpy, DefaultScreen(dpy)) - height)
  231. !     sizeHints->y = DisplayHeight(dpy, DefaultScreen(dpy)) - height;
  232.          
  233.       wmHints = XAllocWMHints();
  234.       if (GRV.VirtualIconic)
  235.       wmHints->initial_state = IconicState;
  236.       else wmHints->initial_state = NormalState;
  237. !     wmHints->flags = StateHint | InputHint | IconPixmapHint | IconPositionHint;
  238.       wmHints->input = TRUE;
  239.       wmHints->icon_pixmap = XCreateBitmapFromData(dpy,
  240.           DefaultRootWindow(dpy), vdm_bits,
  241. --- 170,215 ----
  242.       XSizeHints *sizeHints;
  243.       XWMHints *wmHints;
  244.       XClassHint *classHints;
  245. !     int x, y, dummy, flags;
  246.       Pixmap pm = None;
  247.       unsigned attrMask;
  248. !     int    keysym;
  249. !     char dashList[2];
  250.   
  251.       sizeHints = XAllocSizeHints();
  252.       sizeHints->flags = PBaseSize;
  253. !     sizeHints->base_width = VDMWidth;
  254. !     sizeHints->base_height = VDMHeight;
  255. !     sizeHints->min_width = VDMOutlineWidth;
  256. !     sizeHints->min_height = VDMOutlineHeight;
  257. !     sizeHints->width_inc = VDMOutlineWidth;
  258. !     sizeHints->height_inc = VDMOutlineHeight;
  259. !     if (GRV.VirtualGrid)
  260. !     sizeHints->flags = USPosition | PMinSize | PResizeInc;
  261. !     else sizeHints->flags = USPosition|PMinSize;
  262.       flags = XParseGeometry(GRV.VirtualGeometry, &x, &y, &dummy, &dummy);
  263.       if (flags & XValue)
  264.       if (flags & XNegative)
  265.           sizeHints->x =
  266. !         DisplayWidth(dpy, DefaultScreen(dpy)) + x - VDMWidth;
  267.       else sizeHints->x = x;
  268.       else sizeHints->x = 0;
  269.       if (flags & YValue)
  270.       if (flags & YNegative)
  271.           sizeHints->y =
  272. !         DisplayHeight(dpy, DefaultScreen(dpy)) + y - VDMHeight;
  273.       else sizeHints->y = y;
  274.       else sizeHints->y = 0;
  275. !     if (sizeHints->x > DisplayWidth(dpy, DefaultScreen(dpy)) - VDMWidth)
  276. !     sizeHints->x = DisplayWidth(dpy, DefaultScreen(dpy)) - VDMWidth;
  277. !     if (sizeHints->y > DisplayHeight(dpy, DefaultScreen(dpy)) - VDMHeight)
  278. !     sizeHints->y = DisplayHeight(dpy, DefaultScreen(dpy)) - VDMHeight;
  279.          
  280.       wmHints = XAllocWMHints();
  281.       if (GRV.VirtualIconic)
  282.       wmHints->initial_state = IconicState;
  283.       else wmHints->initial_state = NormalState;
  284. !     wmHints->flags = StateHint | InputHint | IconPixmapHint;
  285.       wmHints->input = TRUE;
  286.       wmHints->icon_pixmap = XCreateBitmapFromData(dpy,
  287.           DefaultRootWindow(dpy), vdm_bits,
  288. ***************
  289. *** 121,140 ****
  290.           vdm_width, vdm_height,
  291.           GRV.Fg1Color, GRV.Bg1Color, 1);
  292.       flags = XParseGeometry(GRV.VirtualIconGeometry, &x, &y, &dummy, &dummy);
  293. !     if (flags & XValue)
  294. !     if (flags & XNegative)
  295. !         wmHints->icon_x = DisplayWidth(dpy, DefaultScreen(dpy)) + x - ICON_SIZE;
  296. !     else wmHints->icon_x = x;
  297. !     else wmHints->icon_x = 0;
  298. !     if (flags & YValue)
  299. !     if (flags & YNegative)
  300. !         wmHints->icon_y = DisplayHeight(dpy, DefaultScreen(dpy)) + y - ICON_SIZE;
  301. !     else wmHints->icon_y = y;
  302. !     else wmHints->icon_y = 0;
  303. !     if (wmHints->icon_x > DisplayWidth(dpy, DefaultScreen(dpy)) - ICON_SIZE)
  304. !     wmHints->icon_x = DisplayWidth(dpy, DefaultScreen(dpy)) - ICON_SIZE;
  305. !     if (wmHints->icon_y > DisplayHeight(dpy, DefaultScreen(dpy)) - ICON_SIZE)
  306. !     wmHints->icon_y = DisplayHeight(dpy, DefaultScreen(dpy)) - ICON_SIZE;
  307.    
  308.       classHints = XAllocClassHint();
  309.       classHints->res_name = "virtualDesktop";
  310. --- 216,240 ----
  311.           vdm_width, vdm_height,
  312.           GRV.Fg1Color, GRV.Bg1Color, 1);
  313.       flags = XParseGeometry(GRV.VirtualIconGeometry, &x, &y, &dummy, &dummy);
  314. !     if (flags & (XValue | YValue)) {
  315. !         if (flags & XValue)
  316. !         if (flags & XNegative)
  317. !             wmHints->icon_x = DisplayWidth(dpy, DefaultScreen(dpy)) +
  318. !                     x - ICON_SIZE;
  319. !         else wmHints->icon_x = x;
  320. !         else wmHints->icon_x = 0;
  321. !         if (flags & YValue)
  322. !         if (flags & YNegative)
  323. !             wmHints->icon_y = DisplayHeight(dpy, DefaultScreen(dpy)) +
  324. !                     y - ICON_SIZE;
  325. !         else wmHints->icon_y = y;
  326. !         else wmHints->icon_y = 0;
  327. !         if (wmHints->icon_x > DisplayWidth(dpy, DefaultScreen(dpy)) - ICON_SIZE)
  328. !         wmHints->icon_x = DisplayWidth(dpy, DefaultScreen(dpy)) - ICON_SIZE;
  329. !         if (wmHints->icon_y > DisplayHeight(dpy, DefaultScreen(dpy)) - ICON_SIZE)
  330. !         wmHints->icon_y = DisplayHeight(dpy, DefaultScreen(dpy)) - ICON_SIZE;
  331. !     wmHints->flags |= IconPositionHint;
  332. !     }
  333.    
  334.       classHints = XAllocClassHint();
  335.       classHints->res_name = "virtualDesktop";
  336. ***************
  337. *** 159,180 ****
  338.       XCopyGC(dpy, RootGC, GCFunction | GCPlaneMask | GCForeground |
  339.                   GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
  340.                   GCJoinStyle | GCFillRule | GCFont, VDMGC);
  341. !     XSetFunction(dpy, VDMGC, GXset);
  342.       XSetFont(dpy, VDMGC, GRV.VirtualFont->fid);
  343.       if (VirtualFontColorSet)
  344.       XSetForeground(dpy, VDMGC, GRV.VirtualFontColor);
  345.       if (VirtualForegroundColorSet)
  346.       XSetBackground(dpy, VDMGC, GRV.VirtualForegroundColor);
  347.       else XSetBackground(dpy, VDMGC, GRV.Bg1Color);
  348. -     if (GRV.VirtualBackgroundMap) {
  349. -     if (pm != None)
  350. -         XFreePixmap(dpy, pm);
  351. -     if (pm = CreateVirtualPixmap(dpy)) {
  352. -         attrMask &= ~CWBackPixel;
  353. -             attrMask |= CWBackPixmap;
  354. -         attr.background_pixmap = pm;
  355. -     }
  356. -     }
  357.   
  358.       VDM = XCreateWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)),
  359.           sizeHints->x, sizeHints->y,
  360. --- 259,274 ----
  361.       XCopyGC(dpy, RootGC, GCFunction | GCPlaneMask | GCForeground |
  362.                   GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
  363.                   GCJoinStyle | GCFillRule | GCFont, VDMGC);
  364. !     XSetFunction(dpy, VDMGC, GXcopy);
  365.       XSetFont(dpy, VDMGC, GRV.VirtualFont->fid);
  366. +     dashList[0] = 0;
  367. +     dashList[1] = 1;
  368. +     XSetDashes( dpy, VDMGC, 1, dashList, 2);
  369.       if (VirtualFontColorSet)
  370.       XSetForeground(dpy, VDMGC, GRV.VirtualFontColor);
  371.       if (VirtualForegroundColorSet)
  372.       XSetBackground(dpy, VDMGC, GRV.VirtualForegroundColor);
  373.       else XSetBackground(dpy, VDMGC, GRV.Bg1Color);
  374.   
  375.       VDM = XCreateWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)),
  376.           sizeHints->x, sizeHints->y,
  377. ***************
  378. *** 181,200 ****
  379.               sizeHints->base_width, sizeHints->base_height, 1,
  380.               DefaultDepth(dpy, DefaultScreen(dpy)), InputOutput,
  381.               CopyFromParent, attrMask, &attr);
  382.       if (pm != None)
  383.       XFreePixmap(dpy, pm);
  384.   
  385. -     VDMWidth = sizeHints->base_width;
  386. -     VDMHeight = sizeHints->base_height;
  387. -     VDMOutlineWidth = VDMWidth /
  388. -             ((width * GRV.VDMScale) /
  389. -                 DisplayWidth(dpy,DefaultScreen(dpy)));
  390. -     VDMOutlineHeight = VDMHeight /
  391. -             ((height * GRV.VDMScale)
  392. -                 / DisplayHeight(dpy,DefaultScreen(dpy)));
  393. -     VDMOutlineX = 0;
  394. -     VDMOutlineY = 0;
  395.       XSetWMProperties(dpy, VDM, &wName, &iName, NULL, 0,
  396.           sizeHints, wmHints, classHints);
  397.       XFree(sizeHints);
  398. --- 275,293 ----
  399.               sizeHints->base_width, sizeHints->base_height, 1,
  400.               DefaultDepth(dpy, DefaultScreen(dpy)), InputOutput,
  401.               CopyFromParent, attrMask, &attr);
  402. +     /*
  403. +      * Have to do this after the VDM is created because of the GC stuff
  404. +      */
  405. +     if (GRV.VirtualBackgroundMap) {
  406. +     if (pm != None)
  407. +         XFreePixmap(dpy, pm);
  408. +     if (pm = CreateVirtualPixmap(dpy))
  409. +         XSetWindowBackgroundPixmap(dpy, VDM, pm);
  410. +     }
  411. +     VWList = ListCons(VDM, VWList);
  412.       if (pm != None)
  413.       XFreePixmap(dpy, pm);
  414.   
  415.       XSetWMProperties(dpy, VDM, &wName, &iName, NULL, 0,
  416.           sizeHints, wmHints, classHints);
  417.       XFree(sizeHints);
  418. ***************
  419. *** 202,207 ****
  420. --- 295,314 ----
  421.       XFree(classHints);
  422.       XMapRaised(dpy, VDM);
  423.   
  424. +     if (!GRV.GrabVirtualKeys)
  425. +     return;
  426. +     for (keysym = XK_R7; keysym <= XK_R15; keysym++)
  427. +     VDMGrabKey(dpy, keysym);
  428. +     /*
  429. +      * Why don't these arrow keys map to R8, R10, R12, R14
  430. +      */
  431. +     VDMGrabKey(dpy, XK_Left);
  432. +     VDMGrabKey(dpy, XK_Right);
  433. +     VDMGrabKey(dpy, XK_Down);
  434. +     VDMGrabKey(dpy, XK_Up);
  435. +     for (keysym = XK_F1; keysym <= XK_F10; keysym++)
  436. +     VDMGrabKey(dpy, keysym);
  437.   }
  438.   
  439.   VirtualSetUpFrame(cli, frame)
  440. ***************
  441. *** 226,233 ****
  442.           GFrameSetConfig(cli->framewin, cli->framewin->core.x - dx,
  443.           cli->framewin->core.y - dy,
  444.           cli->framewin->core.width, cli->framewin->core.height);
  445. -     /*cli->framewin->core.x -= dx;
  446. -     cli->framewin->core.y -= dy;*/
  447.       }
  448.   }
  449.   
  450. --- 333,338 ----
  451. ***************
  452. *** 269,277 ****
  453.       virtual = XCreateSimpleWindow(dpy, VDM, x, y,
  454.       width, height, 1, GRV.BorderColor, 
  455.       VirtualForegroundColorSet ? GRV.VirtualForegroundColor : GRV.Bg1Color);
  456.       if (PANEWINOFCLIENT(cli) != VDM)
  457. !         XSelectInput(dpy, virtual, ButtonPressMask | ExposureMask);
  458. !     else XSelectInput(dpy, virtual, ExposureMask);
  459.       XSaveContext(dpy, virtual, VirtualContext, cli);
  460.       cli->virtualWindow = virtual;
  461.       cli->virtualInactive = MakeVirtualIcon(cli, dpy);
  462. --- 374,383 ----
  463.       virtual = XCreateSimpleWindow(dpy, VDM, x, y,
  464.       width, height, 1, GRV.BorderColor, 
  465.       VirtualForegroundColorSet ? GRV.VirtualForegroundColor : GRV.Bg1Color);
  466. +     VWList = ListCons(virtual, VWList);
  467.       if (PANEWINOFCLIENT(cli) != VDM)
  468. !         XSelectInput(dpy, virtual, VDMSelectMask);
  469. !     else XSelectInput(dpy, virtual, ExposureMask | StructureNotifyMask);
  470.       XSaveContext(dpy, virtual, VirtualContext, cli);
  471.       cli->virtualWindow = virtual;
  472.       cli->virtualInactive = MakeVirtualIcon(cli, dpy);
  473. ***************
  474. *** 309,315 ****
  475.       if (XFindContext(dpy, ev->xany.window, VirtualContext, &cli) != 0)
  476.       return;        /* Window is destroyed . . . */
  477.   
  478. !     XClearArea(dpy, ev->xany.window, 1, 1, 0, 0, False);
  479.       XDrawImageString(dpy, ev->xany.window, VDMGC, 1, 
  480.                   GRV.VirtualFont->max_bounds.ascent + 1,
  481.               cli->framewin->fcore.name,
  482. --- 415,421 ----
  483.       if (XFindContext(dpy, ev->xany.window, VirtualContext, &cli) != 0)
  484.       return;        /* Window is destroyed . . . */
  485.   
  486. !     XClearArea(dpy, ev->xany.window, 0, 0, 0, 0, False);
  487.       XDrawImageString(dpy, ev->xany.window, VDMGC, 1, 
  488.                   GRV.VirtualFont->max_bounds.ascent + 1,
  489.               cli->framewin->fcore.name,
  490. ***************
  491. *** 339,345 ****
  492.       virtual = XCreateSimpleWindow(dpy, VDM, x, y,
  493.           width, height, 1, GRV.BorderColor,
  494.       VirtualForegroundColorSet ? GRV.VirtualForegroundColor : GRV.Bg1Color);
  495. !     XSelectInput(dpy, virtual, ButtonPressMask | KeyPressMask | ExposureMask);
  496.       XSaveContext(dpy, virtual, VirtualContext, cli);
  497.       return virtual;
  498.   }
  499. --- 445,452 ----
  500.       virtual = XCreateSimpleWindow(dpy, VDM, x, y,
  501.           width, height, 1, GRV.BorderColor,
  502.       VirtualForegroundColorSet ? GRV.VirtualForegroundColor : GRV.Bg1Color);
  503. !     VWList = ListCons(virtual, VWList);
  504. !     XSelectInput(dpy, virtual, VDMSelectMask);
  505.       XSaveContext(dpy, virtual, VirtualContext, cli);
  506.       return virtual;
  507.   }
  508. ***************
  509. *** 354,364 ****
  510.       if (ev->xexpose.count)
  511.       return;
  512.   
  513.       XClearArea(dpy, VDM, 0, 0, 0, 0, 0);
  514.       XDrawRectangle(dpy, VDM, VDMGC,
  515. !            VDMOutlineX, VDMOutlineY,
  516. !            VDMOutlineWidth, VDMOutlineHeight);
  517. !     while (XCheckTypedWindowEvent(dpy, VDM, Expose, &dummy));
  518.   }
  519.   
  520.   VDMEvents(dpy, ev)
  521. --- 461,502 ----
  522.       if (ev->xexpose.count)
  523.       return;
  524.   
  525. +     DrawVDMGrid(dpy);
  526. +     while (XCheckTypedWindowEvent(dpy, VDM, Expose, &dummy));
  527. + }
  528. + DrawVDMGrid(dpy)
  529. + Display *dpy;
  530. + {
  531. + int    i;
  532. + XPoint    pts[2];
  533.       XClearArea(dpy, VDM, 0, 0, 0, 0, 0);
  534. +     if (VirtualGridColorSet)
  535. +         XSetForeground(dpy, VDMGC, GRV.VirtualGridColor);
  536. +     if (GRV.VirtualGrid == 2) {
  537. +     XSetLineAttributes(dpy, VDMGC, 1, LineOnOffDash, CapNotLast, JoinMiter);
  538. +     pts[0].y = 0;
  539. +     pts[1].y = VDMHeight;
  540. +     for (i = 0; i < VDMWidth; i += VDMOutlineWidth) {
  541. +         pts[0].x = pts[1].x = i;
  542. +         XDrawLines(dpy, VDM, VDMGC, pts, 2, CoordModeOrigin);
  543. +     }
  544. +     pts[0].x = 0;
  545. +     pts[1].x = VDMWidth;
  546. +     for (i = 0; i < VDMHeight; i += VDMOutlineHeight) {
  547. +         pts[0].y = pts[1].y = i;
  548. +         XDrawLines(dpy, VDM, VDMGC, pts, 2, CoordModeOrigin);
  549. +     }
  550. +     XSetLineAttributes(dpy, VDMGC, 1, LineSolid, CapNotLast, JoinMiter);
  551. +     }
  552.       XDrawRectangle(dpy, VDM, VDMGC,
  553. !     VDMOutlineX, VDMOutlineY, VDMOutlineWidth, VDMOutlineHeight);
  554. !     if (VirtualGridColorSet)
  555. !     if (VirtualFontColorSet)
  556. !         XSetForeground(dpy, VDMGC, GRV.VirtualFontColor);
  557. !     else XSetForeground(dpy, VDMGC, GRV.Fg1Color);
  558.   }
  559.   
  560.   VDMEvents(dpy, ev)
  561. ***************
  562. *** 377,386 ****
  563.           XBell(dpy, 100);
  564.           break;
  565.       case ButtonPress:
  566. !         if (MouseButton(dpy, ev) != MB_SELECT)
  567. !         return;
  568. !         if (HandleVDMButtonPress(dpy, ev))
  569. !         state = 1;
  570.           break;
  571.       case ButtonRelease:
  572.           if (!state)
  573. --- 515,532 ----
  574.           XBell(dpy, 100);
  575.           break;
  576.       case ButtonPress:
  577. !         switch(MouseButton(dpy, ev)) {
  578. !         case MB_SELECT:
  579. !                 if (HandleVDMButtonPress(dpy, ev))
  580. !             state = 1;
  581. !             break;
  582. !         case MB_MENU:
  583. !                 MenuShow(dpy, NULL, &VDMMenu, ev);
  584. !             break;
  585. !         case MB_ADJUST:
  586. !             /* I really should do this someday . . .*/
  587. !             break;
  588. !         }
  589.           break;
  590.       case ButtonRelease:
  591.           if (!state)
  592. ***************
  593. *** 455,469 ****
  594.   }
  595.   #endif
  596.   
  597. ! IsVirtual(w)
  598.       Window    w;
  599.   
  600.   {
  601. !     if (w == VDM)
  602. !     return TRUE;
  603. !     if (!WIGetInfo(w))
  604. !     return TRUE;
  605. !     return FALSE;
  606.   }
  607.   
  608.   VirtualEvents(dpy, ev)
  609. --- 601,633 ----
  610.   }
  611.   #endif
  612.   
  613. ! FindVW(w1, w2)
  614. !     Window    w1, w2;
  615. ! {
  616. !     if (w1 == w2)
  617. !     return w1;
  618. !     return NULL;
  619. ! }
  620. ! IsVirtual(dpy, w)
  621. !     Display    *dpy;
  622.       Window    w;
  623.   
  624.   {
  625. ! Client    *cli;
  626. !     if (ListApply(VWList, FindVW, w) != NULL) {
  627. !     if (XFindContext(dpy, w, VirtualContext, &cli) != 0)
  628. !         /*
  629. !          * REMIND:  Can this happen?  
  630. !          */
  631. !         return True;
  632. !     if (cli->wmState == IconicState)
  633. !         return cli->iconwin->core.self;
  634. !     else return cli->framewin->core.self;
  635. !     }
  636. !     return False;
  637.   }
  638.   
  639.   VirtualEvents(dpy, ev)
  640. ***************
  641. *** 472,477 ****
  642. --- 636,642 ----
  643.   
  644.   {
  645.   Client    *cli;
  646. + Window    dummy;
  647.   
  648.       if (ev->xany.window == VDM)
  649.       VDMEvents(dpy, ev);
  650. ***************
  651. *** 479,494 ****
  652.       case Expose:
  653.           PaintVirtualWindow(dpy, ev);
  654.           break;
  655. !     case ButtonPress:
  656.           /*
  657. !          * Really I should do a select here and then maybe move many, but
  658. !          * I'm too lazy
  659.            */
  660. !         if (MouseButton(dpy, ev) != MB_SELECT)
  661. !         return;
  662.           if (XFindContext(dpy, ev->xany.window, VirtualContext, &cli) != 0)
  663.           return;
  664. !         UserMoveVirtualWindow(dpy, ev, cli);
  665.           break;
  666.       case EnterNotify:
  667.           if (GRV.FocusFollowsMouse &&
  668. --- 644,705 ----
  669.       case Expose:
  670.           PaintVirtualWindow(dpy, ev);
  671.           break;
  672. !     case MotionNotify:
  673. !         if (XFindContext(dpy, ev->xany.window, VirtualContext, &cli) != 0)
  674. !         return;
  675. !         TranslateVirtualCoords(dpy, &ev->xmotion.x_root,
  676. !             &ev->xmotion.y_root, &ev->xmotion.x, &ev->xmotion.y);
  677. !         if (cli->wmState == IconicState) {
  678. !         ev->xany.window = cli->iconwin->core.self;
  679. !             GFrameEventMotionNotify(dpy, ev, cli->iconwin);
  680. !         }
  681. !         else {
  682. !         ev->xany.window = cli->framewin->core.self;
  683. !         GFrameEventMotionNotify(dpy, ev, cli->framewin);
  684. !         }
  685. !         break;
  686. !     case ButtonRelease:
  687. !         if (XFindContext(dpy, ev->xany.window, VirtualContext, &cli) != 0)
  688. !         return;
  689.           /*
  690. !          * We translate events for adjust and select so that those
  691. !          * routines will think we actually selected on the frame.  But
  692. !          * we don't do that for menus, because we want the menu to come
  693. !          * up in the absolute place
  694.            */
  695. !         if (MouseButton(dpy, ev) == MB_MENU)
  696. !             TranslateVirtualCoords(dpy, NULL, NULL,
  697. !                 &ev->xbutton.x, &ev->xbutton.y);
  698. !         else TranslateVirtualCoords(dpy, &ev->xbutton.x_root,
  699. !             &ev->xbutton.y_root, &ev->xbutton.x, &ev->xbutton.y);
  700. !         if (cli->wmState == IconicState) {
  701. !         ev->xany.window = cli->iconwin->core.self;
  702. !             GFrameEventButtonRelease(dpy, ev, cli->iconwin);
  703. !         }
  704. !         else {
  705. !         ev->xany.window = cli->framewin->core.self;
  706. !         GFrameEventButtonRelease(dpy, ev, cli->framewin);
  707. !         }
  708. !         break;
  709. !     case ButtonPress:
  710.           if (XFindContext(dpy, ev->xany.window, VirtualContext, &cli) != 0)
  711.           return;
  712. !         if (MouseButton(dpy, ev) == MB_MENU)
  713. !             TranslateVirtualCoords(dpy, NULL, NULL,
  714. !                 &ev->xbutton.x, &ev->xbutton.y);
  715. !         else TranslateVirtualCoords(dpy, &ev->xbutton.x_root,
  716. !             &ev->xbutton.y_root, &ev->xbutton.x, &ev->xbutton.y);
  717. !         if (cli->wmState == IconicState) {
  718. !         ev->xany.window = cli->iconwin->core.self;
  719. !             GFrameEventButtonPress(dpy, ev, cli->iconwin);
  720. !         }
  721. !         else {
  722. !         ev->xany.window = cli->framewin->core.self;
  723. !         GFrameEventButtonPress(dpy, ev, cli->framewin);
  724. !         }
  725.           break;
  726.       case EnterNotify:
  727.           if (GRV.FocusFollowsMouse &&
  728. ***************
  729. *** 497,502 ****
  730. --- 708,716 ----
  731.               RevertToPointerRoot, CurrentTime);
  732.           }
  733.           break;
  734. +     case DestroyNotify:
  735. +         VWList = ListDestroyCellByValue(ev->xany.window, VWList);
  736. +         break;
  737.       }
  738.   }
  739.   
  740. ***************
  741. *** 509,544 ****
  742.   int    doit = FALSE;
  743.   int    dw = DisplayWidth(dpy, DefaultScreen(dpy));
  744.   int    dh = DisplayHeight(dpy, DefaultScreen(dpy));
  745.   KeySym    symbol;
  746.   enum st_retval ReplaceSticky();
  747.   
  748.       deltas.delta_x = deltas.delta_y = 0;
  749.       symbol = XLookupKeysym(ev, 0);
  750.       switch(symbol) {
  751.       case XK_Left:
  752. !         deltas.delta_x = -dw;
  753.           doit = TRUE;
  754.           break;
  755.       case XK_Up:
  756. !         deltas.delta_y = -dh;
  757.           doit = TRUE;
  758.           break;
  759.       case XK_Right:
  760. !         deltas.delta_x = dw;
  761.           doit = TRUE;
  762.           break;
  763.       case XK_Down:
  764. !         deltas.delta_y = dh;
  765.           doit = TRUE;
  766.           break;
  767.       case XK_R7:
  768. !         deltas.delta_x = -dw;
  769. !         deltas.delta_y = -dh;
  770.           doit = TRUE;
  771.           break;
  772.       case XK_R9:
  773. !         deltas.delta_x = dw;
  774. !         deltas.delta_y = -dh;
  775.           doit = TRUE;
  776.           break;
  777.       case XK_R11:
  778. --- 723,778 ----
  779.   int    doit = FALSE;
  780.   int    dw = DisplayWidth(dpy, DefaultScreen(dpy));
  781.   int    dh = DisplayHeight(dpy, DefaultScreen(dpy));
  782. + int    screen;
  783. + double    factor;
  784.   KeySym    symbol;
  785.   enum st_retval ReplaceSticky();
  786.   
  787. +     if (ev->xkey.type != KeyPress)
  788. +     return;        /* Root window uses same function for Up and Down events */
  789.       deltas.delta_x = deltas.delta_y = 0;
  790.       symbol = XLookupKeysym(ev, 0);
  791. +     switch(ev->xkey.state & (ShiftMask|ControlMask)) {
  792. +     case ShiftMask:
  793. +         factor = 2;
  794. +         break;
  795. +     case ControlMask:
  796. +         factor = .5;
  797. +         break;
  798. +     case ShiftMask|ControlMask:
  799. +         factor = 20;
  800. +         break;
  801. +     default:
  802. +         factor = 1;
  803. +         break;
  804. +     }
  805.       switch(symbol) {
  806.       case XK_Left:
  807. !         deltas.delta_x = -dw * factor;
  808.           doit = TRUE;
  809.           break;
  810.       case XK_Up:
  811. !         deltas.delta_y = -dh * factor;
  812.           doit = TRUE;
  813.           break;
  814.       case XK_Right:
  815. !         deltas.delta_x = dw * factor;
  816.           doit = TRUE;
  817.           break;
  818.       case XK_Down:
  819. !         deltas.delta_y = dh * factor;
  820.           doit = TRUE;
  821.           break;
  822.       case XK_R7:
  823. !         deltas.delta_x = -dw * factor;
  824. !         deltas.delta_y = -dh * factor;
  825.           doit = TRUE;
  826.           break;
  827.       case XK_R9:
  828. !         deltas.delta_x = dw * factor;
  829. !         deltas.delta_y = -dh * factor;
  830.           doit = TRUE;
  831.           break;
  832.       case XK_R11:
  833. ***************
  834. *** 547,586 ****
  835.           doit = TRUE;
  836.           break;
  837.       case XK_R13:
  838. !         deltas.delta_x = -dw;
  839. !         deltas.delta_y = dh;
  840.           doit = TRUE;
  841.           break;
  842.       case XK_R15:
  843. !         deltas.delta_x = dw;
  844. !         deltas.delta_y = dh;
  845.           doit = TRUE;
  846.           break;
  847.       default:
  848.           break;
  849.       }
  850.       if (!doit)
  851.       return FALSE;
  852.   
  853. !     if (VirtualDesktopX - deltas.delta_x < dw - VirtualDesktopWidth)
  854. !     deltas.delta_x = VirtualDesktopX + VirtualDesktopWidth - dw;
  855. !     else if (VirtualDesktopX - deltas.delta_x > 0)
  856. !     deltas.delta_x = VirtualDesktopX;
  857. !     if (VirtualDesktopY - deltas.delta_y < dh - VirtualDesktopHeight)
  858. !     deltas.delta_y = VirtualDesktopY + VirtualDesktopHeight - dh;
  859. !     else if (VirtualDesktopY - deltas.delta_y > 0)
  860. !     deltas.delta_y = VirtualDesktopY;
  861.   
  862.       if (fabs(deltas.delta_x) < 0.1 && fabs(deltas.delta_y) < 0.1)
  863.       return FALSE;
  864. !     VDMOutlineX = (-VirtualDesktopX + deltas.delta_x) / GRV.VDMScale;
  865. !     VDMOutlineY = (-VirtualDesktopY + deltas.delta_y) / GRV.VDMScale;
  866.       MoveDesktop(dpy, &deltas);
  867.       return TRUE;
  868.   }
  869.   
  870.   MoveDesktop(dpy, deltas)
  871.       Display    *dpy;
  872.       struct deltas    *deltas;
  873. --- 781,861 ----
  874.           doit = TRUE;
  875.           break;
  876.       case XK_R13:
  877. !         deltas.delta_x = -dw * factor;
  878. !         deltas.delta_y = dh * factor;
  879.           doit = TRUE;
  880.           break;
  881.       case XK_R15:
  882. !         deltas.delta_x = dw * factor;
  883. !         deltas.delta_y = dh * factor;
  884.           doit = TRUE;
  885.           break;
  886.       default:
  887.           break;
  888.       }
  889. +     if (!doit && symbol >= XK_F1 && symbol <= XK_F10) {
  890. +         switch(ev->xkey.state & (ShiftMask|ControlMask)) {
  891. +         case ShiftMask:
  892. +             factor = 2;
  893. +             break;
  894. +         case ControlMask:
  895. +             factor = 1;
  896. +             break;
  897. +         case ShiftMask|ControlMask:
  898. +             factor = 3;
  899. +             break;
  900. +         default:
  901. +             factor = 0;
  902. +             break;
  903. +         }
  904. +     doit = TRUE;
  905. +     deltas.delta_x = VirtualDesktopX;
  906. +     deltas.delta_y = VirtualDesktopY;
  907. +     screen = symbol - XK_F1 + 10 * factor;
  908. +     deltas.delta_x += dw * (screen % VDMCols);
  909. +     deltas.delta_y += dh * (screen / VDMCols);
  910. +     }
  911.       if (!doit)
  912.       return FALSE;
  913.   
  914. !     constrain_deltas(dpy, &deltas);
  915.   
  916.       if (fabs(deltas.delta_x) < 0.1 && fabs(deltas.delta_y) < 0.1)
  917.       return FALSE;
  918. !     MoveVDMOutline(dpy, &deltas);
  919.       MoveDesktop(dpy, &deltas);
  920.       return TRUE;
  921.   }
  922.   
  923. + MoveVDMOutline(dpy, deltas)
  924. +     Display    *dpy;
  925. +     struct deltas    *deltas;
  926. + {
  927. +     if (deltas->delta_x < 0)
  928. +         VDMOutlineX -= ceil(-deltas->delta_x / GRV.VDMScale);
  929. +     else VDMOutlineX += ceil(deltas->delta_x / GRV.VDMScale);
  930. +     if (deltas->delta_y < 0)
  931. +         VDMOutlineY -= ceil(-deltas->delta_y / GRV.VDMScale);
  932. +     else VDMOutlineY += ceil(deltas->delta_y / GRV.VDMScale);
  933. + }
  934. + constrain_deltas(dpy, deltas)
  935. +     Display        *dpy;
  936. +     struct deltas    *deltas;
  937. + {
  938. + int    dw = DisplayWidth(dpy, DefaultScreen(dpy));
  939. + int    dh = DisplayHeight(dpy, DefaultScreen(dpy));
  940. +     if (VirtualDesktopX - deltas->delta_x < dw - VirtualDesktopWidth)
  941. +     deltas->delta_x = VirtualDesktopX + VirtualDesktopWidth - dw;
  942. +     else if (VirtualDesktopX - deltas->delta_x > 0)
  943. +     deltas->delta_x = VirtualDesktopX;
  944. +     if (VirtualDesktopY - deltas->delta_y < dh - VirtualDesktopHeight)
  945. +     deltas->delta_y = VirtualDesktopY + VirtualDesktopHeight - dh;
  946. +     else if (VirtualDesktopY - deltas->delta_y > 0)
  947. +     deltas->delta_y = VirtualDesktopY;
  948. + }
  949.   MoveDesktop(dpy, deltas)
  950.       Display    *dpy;
  951.       struct deltas    *deltas;
  952. ***************
  953. *** 590,595 ****
  954. --- 865,873 ----
  955.   
  956.       VirtualDesktopX -= deltas->delta_x;
  957.       VirtualDesktopY -= deltas->delta_y;
  958. +     VDMOutlineX = ceil((double) -VirtualDesktopX / GRV.VDMScale);
  959. +     VDMOutlineY = ceil((double) -VirtualDesktopY / GRV.VDMScale);
  960. +     DrawVDMGrid(dpy);
  961.       WIApply(ReplaceSticky, deltas);
  962.       event.xexpose.count = 0;
  963.       HandleVDMExpose(dpy, &event);
  964. ***************
  965. *** 659,664 ****
  966. --- 937,944 ----
  967.   int    VDMPointerX = -1;
  968.   int    VDMPointerY;
  969.   int    VDMInitX, VDMInitY;
  970. + int    VDMLastSelectTime = 0;
  971. + int    NumVDMMoves = 0;
  972.   
  973.   HandleVDMButtonPress(dpy, ev)
  974.       Display    *dpy;
  975. ***************
  976. *** 667,685 ****
  977.   {
  978.       VDMPointerX = ev->xbutton.x;
  979.       VDMPointerY = ev->xbutton.y;
  980. !     if (VDMPointerX < VDMOutlineX ||
  981. !             VDMPointerX > VDMOutlineX + VDMOutlineWidth)
  982. !     return FALSE;
  983. !     if (VDMPointerY < VDMOutlineY ||
  984. !             VDMPointerY > VDMOutlineY + VDMOutlineHeight)
  985. !     return FALSE;
  986. !     XClearWindow(dpy, VDM);
  987.       XDrawRectangle(dpy, VDM, VDMGC,
  988.       VDMOutlineX, VDMOutlineY,
  989.       VDMOutlineWidth, VDMOutlineHeight);
  990.       VDMInitX = VDMOutlineX;
  991.       VDMInitY = VDMOutlineY;
  992. !     return TRUE;
  993.   }
  994.   
  995.   HandleVDMButtonRelease(dpy, ev)
  996. --- 947,960 ----
  997.   {
  998.       VDMPointerX = ev->xbutton.x;
  999.       VDMPointerY = ev->xbutton.y;
  1000. !     XSetFunction(dpy, VDMGC, GXxor);
  1001.       XDrawRectangle(dpy, VDM, VDMGC,
  1002.       VDMOutlineX, VDMOutlineY,
  1003.       VDMOutlineWidth, VDMOutlineHeight);
  1004.       VDMInitX = VDMOutlineX;
  1005.       VDMInitY = VDMOutlineY;
  1006. !     NumVDMMoves = 0;
  1007. !     return True;
  1008.   }
  1009.   
  1010.   HandleVDMButtonRelease(dpy, ev)
  1011. ***************
  1012. *** 688,696 ****
  1013.   
  1014.   {
  1015.   struct deltas    deltas;
  1016.   
  1017. !     XClearWindow(dpy, VDM);
  1018. !     constrain_vdm_outline(ev->xbutton.x, ev->xbutton.y);
  1019.       XDrawRectangle(dpy, VDM, VDMGC, VDMOutlineX, VDMOutlineY,
  1020.       VDMOutlineWidth, VDMOutlineHeight);
  1021.       deltas.delta_x = (VDMOutlineX - VDMInitX) * GRV.VDMScale;
  1022. --- 963,994 ----
  1023.   
  1024.   {
  1025.   struct deltas    deltas;
  1026. + int    dw = DisplayWidth(dpy, DefaultScreen(dpy));
  1027. + int    dh = DisplayHeight(dpy, DefaultScreen(dpy));
  1028.   
  1029. !     XDrawRectangle(dpy, VDM, VDMGC,
  1030. !     VDMOutlineX, VDMOutlineY,
  1031. !     VDMOutlineWidth, VDMOutlineHeight);
  1032. !     XSetFunction(dpy, VDMGC, GXcopy);
  1033. !     if (ev->xbutton.time - VDMLastSelectTime <= GRV.DoubleClickTime) {
  1034. !     deltas.delta_x = VirtualDesktopX;
  1035. !     deltas.delta_y = VirtualDesktopY;
  1036. !     deltas.delta_x += dw * (ev->xbutton.x / VDMOutlineWidth);
  1037. !     deltas.delta_y += dh * (ev->xbutton.y / VDMOutlineHeight);
  1038. !     constrain_deltas(dpy, &deltas);
  1039. !     MoveVDMOutline(dpy, &deltas);
  1040. !     MoveDesktop(dpy, &deltas);
  1041. !     return False;
  1042. !     }
  1043. !     VDMLastSelectTime = ev->xbutton.time;
  1044. !     if (!NumVDMMoves)
  1045. !     return;
  1046. !     constrain_vdm_outline(ev->xbutton.x, ev->xbutton.y,
  1047. !         (GRV.VirtualGrid) ? !(ev->xbutton.state & ControlMask) :
  1048. !                       (ev->xbutton.state & ControlMask));
  1049. !     DrawVDMGrid(dpy);
  1050.       XDrawRectangle(dpy, VDM, VDMGC, VDMOutlineX, VDMOutlineY,
  1051.       VDMOutlineWidth, VDMOutlineHeight);
  1052.       deltas.delta_x = (VDMOutlineX - VDMInitX) * GRV.VDMScale;
  1053. ***************
  1054. *** 706,735 ****
  1055.   {
  1056.       if (VDMPointerX == -1)
  1057.       return;
  1058. -     XClearWindow(dpy, VDM);
  1059. -     constrain_vdm_outline(ev->xmotion.x, ev->xmotion.y);
  1060.       XDrawRectangle(dpy, VDM, VDMGC,
  1061.       VDMOutlineX, VDMOutlineY,
  1062.       VDMOutlineWidth, VDMOutlineHeight);
  1063.   }
  1064.   
  1065. ! constrain_vdm_outline(x, y)
  1066. !     int x, y;
  1067.   
  1068.   {
  1069. !     VDMOutlineX = x - VDMPointerX + VDMInitX;
  1070. !     VDMOutlineY = y - VDMPointerY + VDMInitY;
  1071.       
  1072.       if (VDMOutlineX < 0)
  1073.       VDMOutlineX = 0;
  1074. !     else if (VDMOutlineX + VDMOutlineWidth >= VDMWidth)
  1075. !     VDMOutlineX = VDMWidth - VDMOutlineWidth - 1;
  1076.   
  1077.       if (VDMOutlineY < 0)
  1078.       VDMOutlineY = 0;
  1079. !     else if (VDMOutlineY + VDMOutlineHeight >= VDMHeight)
  1080. !     VDMOutlineY = VDMHeight - VDMOutlineHeight - 1;
  1081.   }
  1082.   
  1083.   int    SaveVDX = -1, SaveVDY;
  1084. --- 1004,1043 ----
  1085.   {
  1086.       if (VDMPointerX == -1)
  1087.       return;
  1088.       XDrawRectangle(dpy, VDM, VDMGC,
  1089.       VDMOutlineX, VDMOutlineY,
  1090.       VDMOutlineWidth, VDMOutlineHeight);
  1091. +     constrain_vdm_outline(ev->xmotion.x, ev->xmotion.y,
  1092. +         (GRV.VirtualGrid) ? !(ev->xbutton.state & ControlMask) :
  1093. +                       (ev->xbutton.state & ControlMask));
  1094. +     XDrawRectangle(dpy, VDM, VDMGC,
  1095. +     VDMOutlineX, VDMOutlineY,
  1096. +     VDMOutlineWidth, VDMOutlineHeight);
  1097. +     NumVDMMoves++;
  1098.   }
  1099.   
  1100. ! constrain_vdm_outline(x, y, snap)
  1101. !     int x, y, snap;
  1102.   
  1103.   {
  1104. !     if (snap) {
  1105. !     VDMOutlineX = (x / VDMOutlineWidth) * VDMOutlineWidth;
  1106. !     VDMOutlineY = (y / VDMOutlineHeight) * VDMOutlineHeight;
  1107. !     }
  1108. !     else {
  1109. !         VDMOutlineX = x - VDMPointerX + VDMInitX;
  1110. !         VDMOutlineY = y - VDMPointerY + VDMInitY;
  1111. !     }
  1112.       
  1113.       if (VDMOutlineX < 0)
  1114.       VDMOutlineX = 0;
  1115. !     else if (VDMOutlineX + VDMOutlineWidth > VDMWidth)
  1116. !     VDMOutlineX = VDMWidth - VDMOutlineWidth;
  1117.   
  1118.       if (VDMOutlineY < 0)
  1119.       VDMOutlineY = 0;
  1120. !     else if (VDMOutlineY + VDMOutlineHeight > VDMHeight)
  1121. !     VDMOutlineY = VDMHeight - VDMOutlineHeight;
  1122.   }
  1123.   
  1124.   int    SaveVDX = -1, SaveVDY;
  1125. ***************
  1126. *** 783,803 ****
  1127.   Client    *cli;
  1128.   
  1129.       if (isUpdate) {
  1130. !         sscanf(GRV.VirtualDesktop, "%dx%d", &width, &height);
  1131. !         if (width < DisplayWidth(dpy,DefaultScreen(dpy)))
  1132. !            width = width * DisplayWidth(dpy,DefaultScreen(dpy));
  1133. !         if (height < DisplayHeight(dpy,DefaultScreen(dpy)))
  1134. !            height = height * DisplayHeight(dpy,DefaultScreen(dpy));
  1135.       if (XFindContext(dpy, VDM, VirtualContext, &cli) != 0)
  1136. !         return TRUE;
  1137. !         GFrameSetConfig(cli->framewin, (int) cli->framewin->core.x,
  1138. !         (int) cli->framewin->core.y,
  1139. !         width / GRV.VDMScale + 1 +
  1140. !         widthLeftFrame(cli->framewin) + widthRightFrame(cli->framewin),
  1141. !         height / GRV.VDMScale + 1 +
  1142. !         heightTopFrame(cli->framewin) + heightBottomFrame(cli->framewin));
  1143.       }
  1144. !     return TRUE;
  1145.   }
  1146.   
  1147.   Bool
  1148. --- 1091,1102 ----
  1149.   Client    *cli;
  1150.   
  1151.       if (isUpdate) {
  1152. !     MakeVirtualDesktop(dpy);
  1153.       if (XFindContext(dpy, VDM, VirtualContext, &cli) != 0)
  1154. !         return True;
  1155. !     ResizeProgVirtual(dpy, cli);
  1156.       }
  1157. !     return True;
  1158.   }
  1159.   
  1160.   Bool
  1161. ***************
  1162. *** 919,925 ****
  1163.   {
  1164.       if (isUpdate) {
  1165.       XSetWindowBackground(dpy, VDM, GRV.VirtualBackgroundColor);
  1166. !     XClearWindow(dpy, VDM);
  1167.       }
  1168.       return TRUE;
  1169.   }
  1170. --- 1218,1224 ----
  1171.   {
  1172.       if (isUpdate) {
  1173.       XSetWindowBackground(dpy, VDM, GRV.VirtualBackgroundColor);
  1174. !         DrawVDMGrid(dpy);
  1175.       }
  1176.       return TRUE;
  1177.   }
  1178. ***************
  1179. *** 973,979 ****
  1180.       if (isUpdate) {
  1181.       if (write = CreateVirtualPixmap(dpy)) {
  1182.           XSetWindowBackgroundPixmap(dpy, VDM, write);
  1183. !         XClearWindow(dpy, VDM);
  1184.           XFreePixmap(dpy, write);
  1185.       }
  1186.       }
  1187. --- 1272,1278 ----
  1188.       if (isUpdate) {
  1189.       if (write = CreateVirtualPixmap(dpy)) {
  1190.           XSetWindowBackgroundPixmap(dpy, VDM, write);
  1191. !             DrawVDMGrid(dpy);
  1192.           XFreePixmap(dpy, write);
  1193.       }
  1194.       }
  1195. ***************
  1196. *** 987,992 ****
  1197. --- 1286,1292 ----
  1198.   Pixmap    read, write;
  1199.   int    w, h, dummy;
  1200.   GC    gc;
  1201. + XGCValues    gcv;
  1202.   
  1203.       if (XReadBitmapFile(dpy, RootWindow(dpy, DefaultScreen(dpy)),
  1204.               GRV.VirtualBackgroundMap, &w, &h,
  1205. ***************
  1206. *** 993,1005 ****
  1207.               &read, &dummy, &dummy) == BitmapSuccess) {
  1208.       write = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)),
  1209.               w, h, DefaultDepth(dpy, DefaultScreen(dpy)));
  1210. !     gc = XCreateGC(dpy, VDM, 0, NULL);
  1211.           XCopyGC(dpy, VDMGC, GCForeground | GCBackground, gc);
  1212. !     /*
  1213. !      * Why doesn't this color stuff work on startup?
  1214. !      */
  1215. !     if (VirtualForegroundColorSet)
  1216. !         XSetForeground(dpy, gc, GRV.VirtualForegroundColor);
  1217.       if (VirtualBackgroundColorSet)
  1218.           XSetBackground(dpy, gc, GRV.VirtualBackgroundColor);
  1219.       XCopyPlane(dpy, read, write, gc, 0, 0, w, h, 0, 0, 1);
  1220. --- 1293,1302 ----
  1221.               &read, &dummy, &dummy) == BitmapSuccess) {
  1222.       write = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)),
  1223.               w, h, DefaultDepth(dpy, DefaultScreen(dpy)));
  1224. !     gcv.function = GXcopy;
  1225. !     gc = XCreateGC(dpy, VDM, GCFunction, &gcv);
  1226.           XCopyGC(dpy, VDMGC, GCForeground | GCBackground, gc);
  1227. !     XSetForeground(dpy, gc, GRV.VirtualPixmapColor);
  1228.       if (VirtualBackgroundColorSet)
  1229.           XSetBackground(dpy, gc, GRV.VirtualBackgroundColor);
  1230.       XCopyPlane(dpy, read, write, gc, 0, 0, w, h, 0, 0, 1);
  1231. ***************
  1232. *** 1019,1059 ****
  1233.   int    doit;
  1234.   struct deltas    deltas;
  1235.   int    temp;
  1236.   
  1237. !     VirtualDesktopHeight = (height - 1) * GRV.VDMScale;
  1238. !     VirtualDesktopWidth = (width - 1) * GRV.VDMScale;
  1239. !     temp = nint((double) VirtualDesktopHeight / 
  1240. !         (double) DisplayHeight(dpy, DefaultScreen(dpy))) *
  1241. !         DisplayHeight(dpy, DefaultScreen(dpy));
  1242. !     if (abs(temp - VirtualDesktopHeight) <= GRV.VDMScale)
  1243. !     VirtualDesktopHeight = temp;
  1244. !     temp = nint((double) VirtualDesktopWidth / 
  1245. !         (double) DisplayWidth(dpy, DefaultScreen(dpy))) *
  1246. !         DisplayWidth(dpy, DefaultScreen(dpy));
  1247. !     if (abs(temp - VirtualDesktopWidth) <= GRV.VDMScale)
  1248. !     VirtualDesktopWidth = temp;
  1249. !     VDMWidth = width;
  1250. !     VDMHeight = height;
  1251.       doit = FALSE;
  1252.       deltas.delta_x = deltas.delta_y = 0;
  1253. !     if (VDMOutlineX + VDMOutlineWidth > VDMWidth - 1) {
  1254.       doit = TRUE;
  1255. !     deltas.delta_x = (VDMWidth - VDMOutlineWidth - 1 -
  1256.           VDMOutlineX) * GRV.VDMScale;
  1257. !         VDMOutlineX = (-VirtualDesktopX + deltas.delta_x) /
  1258. !                 GRV.VDMScale;
  1259.       }
  1260. !     if (VDMOutlineY + VDMOutlineHeight > VDMHeight - 1) {
  1261.       doit = TRUE;
  1262. !     deltas.delta_y = (VDMHeight - VDMOutlineHeight - 1 -
  1263.           VDMOutlineY) * GRV.VDMScale;
  1264. !         VDMOutlineY = (-VirtualDesktopY + deltas.delta_y) /
  1265. !                 GRV.VDMScale;
  1266.       }
  1267.       if (doit) {
  1268.           MoveDesktop(dpy, &deltas);
  1269.              RecursiveRefresh(dpy, VDM);
  1270. !    }
  1271.   }
  1272.   
  1273.   Bool
  1274. --- 1316,1365 ----
  1275.   int    doit;
  1276.   struct deltas    deltas;
  1277.   int    temp;
  1278. + int    dw = DisplayWidth(dpy, DefaultScreen(dpy));
  1279. + int    dh = DisplayHeight(dpy, DefaultScreen(dpy));
  1280.   
  1281. !     if (GRV.VirtualGrid) {
  1282. !         VirtualDesktopHeight = (height - 3) * GRV.VDMScale;
  1283. !         VirtualDesktopHeight = ((VirtualDesktopHeight - 1) / dh + 1) * dh;
  1284. !         VirtualDesktopWidth = (width - 3) * GRV.VDMScale;
  1285. !         VirtualDesktopWidth = ((VirtualDesktopWidth - 1) / dw + 1) * dw;
  1286. !         VDMRows = ceil((double) VirtualDesktopHeight / dh);
  1287. !         VDMCols = ceil((double) VirtualDesktopWidth / dw);
  1288. !         VDMWidth = VDMCols * VDMOutlineWidth;
  1289. !         VDMHeight = VDMRows * VDMOutlineHeight;
  1290. !     }
  1291. !     else {
  1292. !     VirtualDesktopHeight = height * GRV.VDMScale;
  1293. !     VirtualDesktopWidth = width * GRV.VDMScale;
  1294. !         VDMRows = ceil((double) VirtualDesktopHeight / dh);
  1295. !         VDMCols = ceil((double) VirtualDesktopWidth / dw);
  1296. !     VDMWidth = width;
  1297. !     VDMHeight = height;
  1298. !     }
  1299.       doit = FALSE;
  1300.       deltas.delta_x = deltas.delta_y = 0;
  1301. !     if (VDMOutlineX + VDMOutlineWidth > VDMWidth) {
  1302.       doit = TRUE;
  1303. !     deltas.delta_x = (VDMWidth - VDMOutlineWidth -
  1304.           VDMOutlineX) * GRV.VDMScale;
  1305. !         if (deltas.delta_x < 0)
  1306. !             VDMOutlineX -= ceil(-deltas.delta_x / GRV.VDMScale);
  1307. !         else VDMOutlineX += ceil(deltas.delta_x / GRV.VDMScale);
  1308.       }
  1309. !     if (VDMOutlineY + VDMOutlineHeight > VDMHeight) {
  1310.       doit = TRUE;
  1311. !     deltas.delta_y = (VDMHeight - VDMOutlineHeight -
  1312.           VDMOutlineY) * GRV.VDMScale;
  1313. !         if (deltas.delta_y < 0)
  1314. !             VDMOutlineY -= ceil(-deltas.delta_y / GRV.VDMScale);
  1315. !         else VDMOutlineY += ceil(deltas.delta_y / GRV.VDMScale);
  1316.       }
  1317.       if (doit) {
  1318.           MoveDesktop(dpy, &deltas);
  1319.              RecursiveRefresh(dpy, VDM);
  1320. !     }
  1321. !     DrawVDMGrid(dpy);
  1322.   }
  1323.   
  1324.   Bool
  1325. ***************
  1326. *** 1090,1096 ****
  1327.           cli->iconwin->core.width, cli->iconwin->core.height);
  1328.       }
  1329.       }
  1330. !     return TRUE;
  1331.   }
  1332.   
  1333.   VirtualSetColor( dpy, rmIndex, newValue, varSet )
  1334. --- 1396,1402 ----
  1335.           cli->iconwin->core.width, cli->iconwin->core.height);
  1336.       }
  1337.       }
  1338. !     return True;
  1339.   }
  1340.   
  1341.   VirtualSetColor( dpy, rmIndex, newValue, varSet )
  1342. ***************
  1343. *** 1105,1109 ****
  1344. --- 1411,1568 ----
  1345.       VirtualForegroundColorSet = TRUE;
  1346.       else if (rmIndex == RM_VIRTUALFONTCOLOR && newValue)
  1347.       VirtualFontColorSet = TRUE;
  1348. +     else if (rmIndex == RM_VIRTUALGRIDCOLOR && newValue)
  1349. +     VirtualGridColorSet = True;
  1350.       return setColor(dpy, rmIndex, newValue, varSet);
  1351. + }
  1352. + TranslateVirtualCoords(dpy, root_x, root_y, x, y)
  1353. +     int    *root_x, *root_y, *x, *y;
  1354. + {
  1355. + int    tx, ty, tw, th, bw, d;
  1356. + Window    root;
  1357. +     if (x)
  1358. +         *x *= GRV.VDMScale;
  1359. +     if (y)
  1360. +         *y *= GRV.VDMScale;
  1361. +     if (!root_x || !root_y)
  1362. +     return;
  1363. +     XGetGeometry(dpy, VDMFrame, &root, &tx, &ty, &tw, &th, &bw, &d);
  1364. +     *root_x -= tx;
  1365. +     *root_y -= ty;
  1366. +     XGetGeometry(dpy, VDM, &root, &tx, &ty, &tw, &th, &bw, &d);
  1367. +     *root_x -= tx;
  1368. +     *root_y -= ty;
  1369. +     *root_x *= GRV.VDMScale;
  1370. +     *root_x += VirtualDesktopX;
  1371. +     *root_y *= GRV.VDMScale;
  1372. +     *root_y += VirtualDesktopY;
  1373. + }
  1374. + SelectVirtual(cli, state)
  1375. +     Client    *cli;
  1376. +     Bool    state;
  1377. + {
  1378. +     XSetWindowBorderWidth(cli->dpy, cli->virtualWindow, state ? 2 : 1);
  1379. +     XSetWindowBorderWidth(cli->dpy, cli->virtualInactive, state ? 2 : 1);
  1380. + }
  1381. + static int
  1382. + VDMMenuAction(dpy, winInfo, menu, idx, pinnedMenu)
  1383. + Display *dpy;
  1384. + struct _wingeneric    *winInfo;
  1385. + Menu    *menu;
  1386. + int    idx;
  1387. + Bool    pinnedMenu;
  1388. + {
  1389. + struct deltas    deltas;
  1390. + int    dw = DisplayWidth(dpy, DefaultScreen(dpy));
  1391. + int    dh = DisplayHeight(dpy, DefaultScreen(dpy));
  1392. +     switch(idx) {
  1393. +     case VDM_MENU_LEFT:
  1394. +         deltas.delta_x = -dw;
  1395. +         break;
  1396. +     case VDM_MENU_UP:
  1397. +         deltas.delta_y = -dh;
  1398. +         break;
  1399. +     case VDM_MENU_RIGHT:
  1400. +         deltas.delta_x = dw;
  1401. +         break;
  1402. +     case VDM_MENU_DOWN:
  1403. +         deltas.delta_y = dh;
  1404. +         break;
  1405. +     case VDM_MENU_LEFT_UP:
  1406. +         deltas.delta_x = -dw;
  1407. +         deltas.delta_y = -dh;
  1408. +         break;
  1409. +     case VDM_MENU_RIGHT_UP:
  1410. +         deltas.delta_x = dw;
  1411. +         deltas.delta_y = -dh;
  1412. +         break;
  1413. +     case VDM_MENU_HOME:
  1414. +         deltas.delta_x = VirtualDesktopX;
  1415. +         deltas.delta_y = VirtualDesktopY;
  1416. +         break;
  1417. +     case VDM_MENU_LEFT_DOWN:
  1418. +         deltas.delta_x = -dw;
  1419. +         deltas.delta_y = dh;
  1420. +         break;
  1421. +     case VDM_MENU_RIGHT_DOWN:
  1422. +         deltas.delta_x = dw;
  1423. +         deltas.delta_y = dh;
  1424. +         break;
  1425. +     }
  1426. +     constrain_deltas(dpy, &deltas);
  1427. +     if (fabs(deltas.delta_x) < 0.1 && fabs(deltas.delta_y) < 0.1)
  1428. +     return FALSE;
  1429. +     MoveVDMOutline(dpy, &deltas);
  1430. +     MoveDesktop(dpy, &deltas);
  1431. + }
  1432. + Bool
  1433. + UpdVirtualGrid(dpy, rmIndex, isUpdate)
  1434. +     Display    *dpy;
  1435. +     int        rmIndex;
  1436. +     Bool    isUpdate;
  1437. + {
  1438. + Client    *cli;
  1439. +     if (isUpdate) {
  1440. +     cli = VirtualGetClient(dpy, VDM);
  1441. +     if (!cli)
  1442. +         return True;
  1443. +     ResizeVDM(dpy, 
  1444. +         cli->framewin->core.width -
  1445. +           widthLeftFrame(cli->framewin) - widthRightFrame(cli->framewin),
  1446. +         cli->framewin->core.height -
  1447. +           heightTopFrame(cli->framewin) - heightBottomFrame(cli->framewin));
  1448. +     if (GRV.VirtualGrid) {
  1449. +         cli->normHints->flags |= PResizeInc;
  1450. +         ResizeProgVirtual(dpy, cli);
  1451. +     }
  1452. +     else cli->normHints->flags &= ~PResizeInc;
  1453. +     }
  1454. +     DrawVDMGrid(dpy);
  1455. +     return True;
  1456. + }
  1457. + ResizeProgVirtual(dpy, cli)
  1458. + Display    *dpy;
  1459. + Client    *cli;
  1460. + {
  1461. +     GFrameSetConfig(cli->framewin,
  1462. +     cli->framewin->core.x, cli->framewin->core.y,
  1463. +     VDMWidth + widthLeftFrame(cli->framewin) +
  1464. +             widthRightFrame(cli->framewin),
  1465. +     VDMHeight + heightTopFrame(cli->framewin) +
  1466. +             heightBottomFrame(cli->framewin));
  1467. + }
  1468. + SetGridResource(dpy, rmIndex, newValue, varSet)
  1469. + Display    *dpy;
  1470. + int    rmIndex;
  1471. + char    *newValue;
  1472. + Bool    varSet;
  1473. + {
  1474. + int    new, ret;
  1475. +     if (!newValue)
  1476. +     new = 2;
  1477. +     else if (matchString(newValue, "none"))
  1478. +     new = 0;
  1479. +     else if (matchString(newValue, "invisible"))
  1480. +     new = 1;
  1481. +     else new = 2;
  1482. +     ret = new != GRV.VirtualGrid;
  1483. +     GRV.VirtualGrid = new;
  1484. +     return ret;
  1485.   }
  1486. *** build/win.c    Sat Jun 22 20:09:02 1991
  1487. --- src/win.c    Sat Jun 22 20:56:18 1991
  1488. ***************
  1489. *** 6,12 ****
  1490.    *    Written for Sun Microsystems by Crucible, Santa Cruz, CA.
  1491.    */
  1492.   
  1493. ! static char     sccsid[] = "@(#)win.c    1.2 olvwm version 3/30/91";
  1494.   
  1495.   /*
  1496.    * Based on
  1497. --- 6,12 ----
  1498.    *    Written for Sun Microsystems by Crucible, Santa Cruz, CA.
  1499.    */
  1500.   
  1501. ! static char     sccsid[] = "@(#)win.c    1.3 olvwm version 6/22/91";
  1502.   
  1503.   /*
  1504.    * Based on
  1505. ***************
  1506. *** 147,152 ****
  1507. --- 147,153 ----
  1508.           callSelectTree(cli->dpy, cli->framewin, sel);
  1509.       else if (cli->wmState == IconicState)
  1510.           callSelectTree(cli->dpy, cli->iconwin, sel);
  1511. +     SelectVirtual(cli, sel);
  1512.   }
  1513.   
  1514.   /* WinCallFocus - call a client's focus functions for the frame tree.
  1515. ***************
  1516. *** 157,166 ****
  1517. --- 158,179 ----
  1518.   WinGeneric *win;
  1519.   Bool focus;
  1520.   {
  1521. + XEvent    ev;
  1522.       if (win == NULL)
  1523.           return;
  1524.       win->core.client->isFocus = focus;
  1525.       callFocusTree(win, focus);
  1526. +     if (!focus && XCheckWindowEvent(win->core.client->dpy,
  1527. +                 win->core.self, DestroyNotify, &ev)) {
  1528. +         /*
  1529. +          * When a window goes away, we get first the Focus event and
  1530. +          * then the destroy event -- so we have to mark the client
  1531. +          * as still having focus so StateWithdrawn will work ok
  1532. +          */
  1533. +         XPutBackEvent(win->core.client->dpy, &ev);
  1534. +         win->core.client->isFocus = 1;
  1535. +     }
  1536.   }
  1537.       
  1538.   /* WinCallDestroy - call a client's destroy functions for both the icon and
  1539. *** build/winframe.c    Sat Jun 22 20:09:44 1991
  1540. --- src/winframe.c    Sat Jun 22 20:56:19 1991
  1541. ***************
  1542. *** 6,12 ****
  1543.    *    Written for Sun Microsystems by Crucible, Santa Cruz, CA.
  1544.    */
  1545.   
  1546. ! static char     sccsid[] = "@(#)winframe.c    1.3 olvwm version 4/17/91";
  1547.   
  1548.   /*
  1549.    * Based on
  1550. --- 6,12 ----
  1551.    *    Written for Sun Microsystems by Crucible, Santa Cruz, CA.
  1552.    */
  1553.   
  1554. ! static char     sccsid[] = "@(#)winframe.c    1.4 olvwm version 6/22/91";
  1555.   
  1556.   /*
  1557.    * Based on
  1558. ***************
  1559. *** 1171,1181 ****
  1560.    * get the event, set the focus, and replay the event, thus passing the event
  1561.    * through.
  1562.    *
  1563. -  * SDO:  We seem to get the event anyway.  And grabbing the button seemed
  1564. -  *     to cause lots of problems anyway, due perhaps to the grab bugs
  1565. -  *     in xnews, but whatever; if the button press was destined for the
  1566. -  *     VDM, we never got the button up (or anything else . . .).  And
  1567. -  * 
  1568.    * REMIND we need to remove explicit reference to Buttons 1 and 2.
  1569.    */
  1570.   void
  1571. --- 1171,1176 ----
  1572. ***************
  1573. *** 1184,1190 ****
  1574.       Window win;
  1575.       Bool activate;
  1576.   {
  1577. - #ifdef NOTDEF
  1578.       if (!GRV.FocusFollowsMouse) {
  1579.       switch (cli->focusMode) {
  1580.       case Passive:
  1581. --- 1179,1184 ----
  1582. ***************
  1583. *** 1203,1209 ****
  1584.           break;
  1585.       }
  1586.       }
  1587. - #endif
  1588.   }
  1589.   
  1590.   
  1591. --- 1197,1202 ----
  1592.  
  1593. --
  1594. Dan Heller
  1595. O'Reilly && Associates       Z-Code Software    Comp-sources-x:
  1596. Senior Writer                President          comp-sources-x@uunet.uu.net
  1597. argv@ora.com                 argv@zipcode.com
  1598.